package com.example.offer;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.TreeMap;

/**
 * 239. 滑动窗口最大值
 * 给你一个整数数组 nums，有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
 * <p>
 * 返回滑动窗口中的最大值。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：nums = [1,3,-1,-3,5,3,6,7], k = 3
 * 输出：[3,3,5,5,6,7]
 * 解释：
 * 滑动窗口的位置                最大值
 * ---------------               -----
 * [1  3  -1] -3  5  3  6  7      3
 * 1 [3  -1  -3] 5  3  6  7       3
 * 1  3 [-1  -3  5] 3  6  7       5
 * 1  3  -1 [-3  5  3] 6  7       5
 * 1  3  -1  -3 [5  3  6] 7       6
 * 1  3  -1  -3  5 [3  6  7]      7
 */
public class Solutionrrr {
    public static int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        PriorityQueue<int[]> stack = new PriorityQueue<>(k, (a, b) -> b[0] - a[0]);
        int[] res = new int[n - k + 1];
        for (int i = 0; i < n; i++) {
            stack.add(new int[]{nums[i], i});
            if (i - k + 1 >= 0) {
                //注意这里是while ，如果头部一直在边界外，则一直删。通过poll删除要比remove效率快很多
                while (stack.peek()[1] <= (i - k)) stack.poll();
                res[i - k + 1] = stack.peek()[0];
            }
        }
        return res;
    }

    /**
     * treemap解法
     */
    public static int[] maxSlidingWindow2(int[] nums, int k) {
        int n = nums.length;
        //reverse会将值大的放入key放在头部，通过firstKey取出来
        TreeMap<Integer, Integer> integerIntegerTreeMap = new TreeMap<>(Comparator.reverseOrder());
        int[] res = new int[n - k + 1];
        for (int i = 0; i < n; i++) {
            integerIntegerTreeMap.put(nums[i], i);
            if (i - k + 1 >= 0) {
                //注意这里是while ，如果头部一直在边界外，则一直删。通过poll删除要比remove效率快很多
                while (integerIntegerTreeMap.firstEntry().getValue() <= (i - k))
                    integerIntegerTreeMap.remove(integerIntegerTreeMap.firstKey());
                res[i - k + 1] = integerIntegerTreeMap.firstKey();
            }
        }
        return res;
    }


    public static void main(String[] args) {
        Solutionrrr.maxSlidingWindow2(new int[]{9, 10, 9, -7, -4, -8, 2, -6}, 5);
    }
}
